www.gusucode.com > 网页滑动条(滑块)Accessible Unobtrusive Slider 插件示例源码程序 > 网页滑动条(滑块)Accessible Unobtrusive Slider 插件示例/sliderv2/slider-v2/slider.js

    /*
        Unobtrusive Slider Control by frequency decoder v2.4 (http://www.frequency-decoder.com/)

        Released under a creative commons Attribution-Share Alike 3.0 Unported license (http://creativecommons.org/licenses/by-sa/3.0/)

        You are free:

        * to copy, distribute, display, and perform the work
        * to make derivative works
        * to make commercial use of the work

        Under the following conditions:

                by Attribution.
                --------------
                You must attribute the work in the manner specified by the author or licensor.

                sa
                --
                Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

        * For any reuse or distribution, you must make clear to others the license terms of this work.
        * Any of these conditions can be waived if you get permission from the copyright holder.
*/

var fdSliderController = (function() {
        var sliders           = {},
            uniqueid          = 0,
            mouseWheelEnabled = true;
                
        var removeMouseWheelSupport = function() {
                mouseWheelEnabled = false;
        };                       
        var addEvent = function(obj, type, fn) {
                if( obj.attachEvent ) {
                        obj["e"+type+fn] = fn;
                        obj[type+fn] = function(){obj["e"+type+fn]( window.event );};
                        obj.attachEvent( "on"+type, obj[type+fn] );
                } else { obj.addEventListener( type, fn, true ); }
        };
        var removeEvent = function(obj, type, fn) {
                if( obj.detachEvent ) {
                        try {
                                obj.detachEvent( "on"+type, obj[type+fn] );
                                obj[type+fn] = null;
                        } catch(err) { };
                } else { obj.removeEventListener( type, fn, true ); }
        };
        var stopEvent = function(e) {
                if(e == null) e = document.parentWindow.event;
                if(e.stopPropagation) {
                        e.stopPropagation();
                        e.preventDefault();
                };
                
                /*@cc_on@*/
                /*@if(@_win32)
                e.cancelBubble = true;
                e.returnValue = false;
                /*@end@*/
                
                return false;
        };                                           
        var joinNodeLists = function() {
                if(!arguments.length) { return []; };
                var nodeList = [];
                for (var i = 0; i < arguments.length; i++) {
                        for (var j = 0, item; item = arguments[i][j]; j++) { nodeList[nodeList.length] = item; };
                };
                return nodeList;
        };

        // Function by Artem B. with a minor change by f.d.
        var parseCallbacks = function(cbs) {
                if(cbs == null) { return {}; };
                var func,
                    type,
                    cbObj = {},
                    parts,
                    obj;
                for(var i = 0, fn; fn = cbs[i]; i++) {
                        type = fn.match(/(fd_slider_cb_(update|create|destroy|redraw|move|focus|blur)_)([^\s|$]+)/i)[1];
                        fn   = fn.replace(new RegExp("^"+type), "").replace(/-/g, ".");
                        type = type.replace(/^fd_slider_cb_/i, "").replace(/_$/, "");

                        try {
                                if(fn.indexOf(".") != -1) {
                                        parts = fn.split('.');
                                        obj   = window;
                                        for (var x = 0, part; part = obj[parts[x]]; x++) {
                                                if(part instanceof Function) {
                                                        (function() {
                                                                var method = part;
                                                                func = function (data) { method.apply(obj, [data]) };
                                                        })();
                                                } else {
                                                obj = part;
                                                };
                                        };
                                } else {
                                        func = window[fn];
                                };
                            
                                if(!(func instanceof Function)) continue;
                                if(!(type in cbObj)) { cbObj[type] = []; };
                                cbObj[type][cbObj[type].length] = func;
                        } catch (err) {};
                };
                return cbObj;
        };
                
        var parseClassNames = function(cbs) {
                if(cbs == null) { return ""; };
                var cns = [];                    
                for(var i = 0, cn; cn = cbs[i]; i++) { 
                        cns[cns.length] = cn.replace(/^fd_slider_cn_/, "");                                                                 
                };                 
                return cns.join(" ");
        };
        var createSlider = function(options) {
                if(!options.inp || !options.inp.id) { return false; };
                destroySingleSlider(options.inp.id);
                sliders[options.inp.id] = new fdSlider(options);
                return true;
        };                
        var init = function( elem ) {
                var ranges     = /fd_range_([-]{0,1}[0-9]+(d[0-9]+){0,1}){1}_([-]{0,1}[0-9]+(d[0-9]+){0,1}){1}/i,
                    increment  = /fd_inc_([-]{0,1}[0-9]+(d[0-9]+){0,1}){1}/,
                    kIncrement = /fd_maxinc_([-]{0,1}[0-9]+(d[0-9]+){0,1}){1}/,
                    callbacks  = /((fd_slider_cb_(update|create|destroy|redraw|move|focus|blur)_)([^\s|$]+))/ig, 
                    classnames = /(fd_slider_cn_([a-zA-Z0-9_\-]+))/ig,
                    inputs     = elem && elem.tagName && elem.tagName.search(/input|select/i) != -1 ? [elem] : joinNodeLists(document.getElementsByTagName('input'), document.getElementsByTagName('select')),
                    range, 
                    tmp, 
                    options;

                for(var i = 0, inp; inp = inputs[i]; i++) {
                        if((inp.tagName.toLowerCase() == "input" && inp.type == "text" && (inp.className.search(ranges) != -1 || inp.className.search(/fd_slider/) != -1)) || (inp.tagName.toLowerCase() == "select" && inp.className.search(/fd_slider/) != -1)) {
                                // If we haven't been passed a specific id and the slider exists then continue
                                if(!elem && inp.id && document.getElementById("fd-slider-"+inp.id)) { continue; };
                                        
                                // Create an id if necessary
                                if(!inp.id) { inp.id == "sldr" + uniqueid++; };                       
                                        
                                options = {
                                        inp:            inp,
                                        inc:            inp.className.search(increment)  != -1 ? inp.className.match(increment)[0].replace("fd_inc_", "").replace("d",".") : "1",
                                        maxInc:         inp.className.search(kIncrement) != -1 ? inp.className.match(kIncrement)[0].replace("fd_maxinc_", "").replace("d",".") : false,
                                        range:          [0,100],
                                        callbacks:      parseCallbacks(inp.className.match(callbacks)),
                                        classNames:     parseClassNames(inp.className.match(classnames)),
                                        tween:          inp.className.search(/fd_tween/i) != -1,
                                        vertical:       inp.className.search(/fd_vertical/i) != -1,
                                        hideInput:      inp.className.search(/fd_hide_input/i) != -1,
                                        clickJump:      inp.className.search(/fd_jump/i) != -1,
                                        fullARIA:       inp.className.search(/fd_full_aria/i) != -1,
                                        noMouseWheel:   inp.className.search(/fd_disable_mousewheel/i) != -1
                                };
                                        
                                if(inp.tagName.toLowerCase() == "select") {
                                        options.range = [0, inp.options.length - 1];                                                
                                } else if(inp.className.search(ranges) != -1) {                                                
                                        range = inp.className.match(ranges)[0].replace("fd_range_", "").replace(/d/g,".").split("_");                                                 
                                        options.range = [range[0], range[1]];                                                                                                  
                                };                                       
                                        
                                createSlider(options);                                        
                        };
                };
                return true;
        };
        var destroySingleSlider = function(id) {
                if(id in sliders) { 
                        sliders[id].destroy(); 
                        delete sliders[id]; 
                        return true;
                };
                return false;
        };
        var destroyAllsliders = function(e) {
                for(slider in sliders) { sliders[slider].destroy(); };                        
        };
        var unload = function(e) {
                destroyAllsliders();
                sliders = null;                         
                removeEvent(window, "unload", unload);
                removeEvent(window, "resize", resize);
                removeOnloadEvent();
        };                  
        var resize = function(e) {
                for(slider in sliders) { sliders[slider].onResize(); };        
        };                 
        var removeOnloadEvent = function() {
                removeEvent(window, "load", init);
                /*@cc_on@*/
                /*@if(@_win32)
                removeEvent(window, "load",   function() { setTimeout(onload, 200) });
                /*@end@*/
        };              
        function fdSlider(options) {
                var inp         = options.inp,
                    tagName     = inp.tagName.toLowerCase(),                      
                    min         = +options.range[0],
                    max         = +options.range[1], 
                    range       = Math.abs(max - min),
                    inc         = tagName == "select" ? 1 : +options.inc||1,
                    maxInc      = options.maxInc ? options.maxInc : inc * 2,
                    precision   = options.inc.search(".") != -1 ? options.inc.substr(options.inc.indexOf(".")+1, options.inc.length - 1).length : 0,
                    steps       = Math.ceil(range / inc),
                    useTween    = !!options.tween,
                    fullARIA    = !!options.fullARIA,
                    hideInput   = !!options.hideInput,                                                 
                    clickJump   = useTween ? false : !!options.clickJump,                                        
                    vertical    = !!options.vertical,
                    callbacks   = options.callbacks,
                    classNames  = options.classNames,
                    noMWheel    = !!options.noMouseWheel,                    
                    timer       = null,
                    kbEnabled   = true,                    
                    sliderH     = 0,
                    sliderW     = 0, 
                    tweenX      = 0,
                    tweenB      = 0,
                    tweenC      = 0,
                    tweenD      = 0,
                    frame       = 0,
                    x           = 0,                    
                    y           = 0,                    
                    maxPx       = 0,
                    handlePos   = 0,                    
                    destPos     = 0,                    
                    mousePos    = 0,
                    deltaPx     = 0, 
                    stepPx      = 0,
                    self        = this,
                    changeList  = {},
                    initVal     = null,
                    outerWrapper,
                    wrapper,
                    handle,
                    bar;                                 
                  
                if(max < min) {
                        inc    = -inc;
                        maxInc = -maxInc;
                };
                 
                function destroySlider() {
                        try {                                         
                                removeEvent(outerWrapper, "mouseover", onMouseOver);
                                removeEvent(outerWrapper, "mouseout",  onMouseOut);
                                removeEvent(outerWrapper, "mousedown", onMouseDown);
                                removeEvent(handle, "focus",     onFocus);
                                removeEvent(handle, "blur",      onBlur);                        
                                if(!window.opera) {
                                        removeEvent(handle, "keydown",   onKeyDown);  
                                        removeEvent(handle, "keypress",  onKeyPress); 
                                } else {
                                        removeEvent(handle, "keypress",  onKeyDown);
                                };                                             
                                removeEvent(handle, "mousedown", onHandleMouseDown);
                                removeEvent(handle, "mouseup",   onHandleMouseUp);

                                if(mouseWheelEnabled && !noMWheel) {
                                        if (window.addEventListener && !window.devicePixelRatio) window.removeEventListener('DOMMouseScroll', trackMouseWheel, false);
                                        else {
                                                removeEvent(document, "mousewheel", trackMouseWheel);
                                                removeEvent(window,   "mousewheel", trackMouseWheel);
                                        };
                                };
                        } catch(err) {};
                        wrapper = bar = handle = outerWrapper = timer = null;
                        callback("destroy");
                        callbacks = null;
                };
                
                function redraw() {
                        locate();
                        // Internet Explorer requires the try catch
                        try {
                                var sW = outerWrapper.offsetWidth,
                                    sH = outerWrapper.offsetHeight,
                                    hW = handle.offsetWidth,
                                    hH = handle.offsetHeight,
                                    bH = bar.offsetHeight,
                                    bW = bar.offsetWidth; 
                                
                                maxPx     = vertical ? sH - hH : sW - hW;
                                stepPx    = maxPx / steps;                                                 
                                deltaPx   = maxPx / Math.ceil(range / maxInc);
                                
                                sliderW = sW;
                                sliderH = sH;
                                
                                valueToPixels();
                        } catch(err) { };
                        callback("redraw");
                };
                
                function callback(type) {
                        
                        var cbObj = {"elem":inp, "value":tagName == "select" ? inp.options[inp.selectedIndex].value : inp.value};
                        if(type in callbacks) {
                                for(var i = 0, func; func = callbacks[type][i]; i++) {
                                        func(cbObj);
                                };
                        }; 
                };

                function onFocus(e) {
                        outerWrapper.className = outerWrapper.className.replace('focused','') + ' focused';
                        if(mouseWheelEnabled && !noMWheel) {
                                addEvent(window, 'DOMMouseScroll', trackMouseWheel);
                                addEvent(document, 'mousewheel', trackMouseWheel);
                                if(!window.opera) addEvent(window,   'mousewheel', trackMouseWheel); 
                        }; 
                        callback("focus");                      
                };
                
                function onBlur(e) {
                        outerWrapper.className = outerWrapper.className.replace(/focused|fd-fc-slider-hover|fd-slider-hover/g,'');
                        if(mouseWheelEnabled && !noMWheel) {
                                removeEvent(document, 'mousewheel', trackMouseWheel);
                                removeEvent(window, 'DOMMouseScroll', trackMouseWheel);
                                if(!window.opera) removeEvent(window,   'mousewheel', trackMouseWheel);
                        };
                        callback("blur");
                };
                
                function trackMouseWheel(e) {
                        if(!kbEnabled) return;
                        e = e || window.event;
                        var delta = 0;
                            
                        if (e.wheelDelta) {
                                delta = e.wheelDelta/120;
                                if (window.opera && window.opera.version() < 9.2) delta = -delta;
                        } else if(e.detail) {
                                delta = -e.detail/3;
                        };
                        
                        if(vertical) { delta = -delta; };
                        
                        if(delta) {
                                var xtmp = vertical ? handle.offsetTop : handle.offsetLeft;
                                xtmp = (delta < 0) ? Math.ceil(xtmp + deltaPx) : Math.floor(xtmp - deltaPx);                                
                                pixelsToValue(Math.min(Math.max(xtmp, 0), maxPx));
                        }
                        return stopEvent(e);
                };                  
                
                function onKeyPress(e) {                        
                        e = e || document.parentWindow.event;                         
                        if ((e.keyCode >= 33 && e.keyCode <= 40) || !kbEnabled || e.keyCode == 45 || e.keyCode == 46) {                                 
                                return stopEvent(e);
                        };
                        return true;
                };               
                        
                function onKeyDown(e) {
                        if(!kbEnabled) return true;

                        e = e || document.parentWindow.event;
                        var kc = e.keyCode != null ? e.keyCode : e.charCode;
                        
                        if ( kc < 33 || (kc > 40 && (kc != 45 && kc != 46))) return true;

                        var value = tagName == "input" ? parseFloat(inp.value) : inp.selectedIndex;
                        if(isNaN(value) || value < Math.min(min,max)) value = Math.min(min,max);    
                        
                        if( kc == 37 || kc == 40 || kc == 46 || kc == 34) {
                                // left, down, ins, page down                                                              
                                value -= (e.ctrlKey || kc == 34 ? maxInc : inc)
                        } else if( kc == 39 || kc == 38 || kc == 45 || kc == 33) {
                                // right, up, del, page up                                                                  
                                value += (e.ctrlKey || kc == 33 ? maxInc : inc)
                        } else if( kc == 35 ) {
                                // max                                
                                value = max;
                        } else if( kc == 36 ) {
                                // min                                
                                value = min;
                        };  
                        
                        valueToPixels(value);
                        callback("update");
                        
                        // Opera doesn't let us cancel key events so the up/down arrows and home/end buttons will scroll the screen - which sucks
                        return stopEvent(e);
                };                                     
                               
                function onMouseOver( e ) {
                        /*@cc_on@*/
                        /*@if(@_jscript_version <= 5.6)
                        if(this.className.search(/focused/) != -1) {
                                this.className = this.className.replace("fd-fc-slider-hover", "") +' fd-fc-slider-hover';
                                return;
                        }
                        /*@end@*/
                        this.className = this.className.replace(/fd\-slider\-hover/g,"") +' fd-slider-hover';
                };  
                              
                function onMouseOut( e ) {
                        /*@cc_on@*/
                        /*@if(@_jscript_version <= 5.6)
                        if(this.className.search(/focused/) != -1) {
                                this.className = this.className.replace("fd-fc-slider-hover", "");
                                return;
                        }
                        /*@end@*/
                        this.className = this.className.replace(/fd\-slider\-hover/g,"");
                };
                
                function onHandleMouseUp(e) {
                        e = e || window.event;
                        removeEvent(document, 'mousemove', trackMouse);
                        removeEvent(document, 'mouseup',   onHandleMouseUp);
                        
                        kbEnabled = true;

                        // Opera fires the blur event when the mouseup event occurs on a button, so we attept to force a focus
                        if(window.opera) try { setTimeout(function() { onfocus(); }, 0); } catch(err) {};
                        document.body.className = document.body.className.replace(/slider-drag-vertical|slider-drag-horizontal/g, "");
                              
                        return stopEvent(e);
                };
                
                function onHandleMouseDown(e) {
                        e = e || window.event;
                        mousePos  = vertical ? e.clientY : e.clientX;
                        handlePos = parseInt(vertical ? handle.offsetTop : handle.offsetLeft)||0;                        
                        kbEnabled = false;
                        
                        clearTimeout(timer);
                        timer = null;
                                
                        addEvent(document, 'mousemove', trackMouse);
                        addEvent(document, 'mouseup', onHandleMouseUp);
                                
                        // Force a "focus" on the button on mouse events
                        if(window.devicePixelRatio || (document.all && !window.opera)) try { setTimeout(function() { handle.focus(); }, 0); } catch(err) {};
                        
                        document.body.className += " slider-drag-" + (vertical ? "vertical" : "horizontal");
                };
                
                function onMouseUp( e ) {
                        e = e || window.event;
                        removeEvent(document, 'mouseup', onMouseUp);
                        if(!useTween) {
                                clearTimeout(timer);
                                timer = null;
                                kbEnabled = true;
                        };                        
                        return stopEvent(e);
                };
                
                function trackMouse( e ) {                                                  
                        e = e || window.event;                        
                        pixelsToValue(snapToNearestValue(handlePos + (vertical ? e.clientY - mousePos : e.clientX - mousePos)));                                          
                };
                
                function onMouseDown( e ) {
                        e = e || window.event;
                        var targ;                          
                        if (e.target) targ = e.target;
                        else if (e.srcElement) targ = e.srcElement;
                        if (targ.nodeType == 3) targ = targ.parentNode;

                        if(targ.className.search("fd-slider-handle") != -1) { return true; };
                                
                        try { setTimeout(function() { handle.focus(); }, 0); } catch(err) { };                                               
                        
                        clearTimeout(timer);
                        locate();
                        
                        timer     = null;
                        kbEnabled = false;                           
                        
                        var posx        = 0,
                            sLft        = 0,
                            sTop        = 0;

                        // Internet Explorer doctype woes
                        if (document.documentElement && document.documentElement.scrollTop) {
                                sTop = document.documentElement.scrollTop;
                                sLft = document.documentElement.scrollLeft;
                        } else if (document.body) {
                                sTop = document.body.scrollTop;
                                sLft = document.body.scrollLeft;
                        };

                        if (e.pageX)            posx = vertical ? e.pageY : e.pageX;
                        else if (e.clientX)     posx = vertical ? e.clientY + sTop : e.clientX + sLft;
                        posx -= vertical ? y + Math.round(handle.offsetHeight / 2) : x + Math.round(handle.offsetWidth / 2);                         
                        posx = snapToNearestValue(posx);                         
                        
                        if(useTween) {
                                tweenTo(posx);
                        } else if(clickJump) {
                                pixelsToValue(posx);
                        } else {
                                addEvent(document, 'mouseup', onMouseUp);
                                destPos = posx;
                                onTimer();
                        };                    
                };

                function incrementHandle(numOfSteps) { 
                        var value = tagName == "input" ? parseFloat(inp.value) : inp.selectedIndex;
                        if(isNaN(value) || value < Math.min(min,max)) value = Math.min(min,max);  
                        value += inc * numOfSteps;
                        valueToPixels(value);                                               
                };
                
                function snapToNearestValue(px) {
                        var rem = px % stepPx;
                        if(rem && rem >= (stepPx / 2)) { px += (stepPx - rem); } 
                        else { px -= rem;  };                        
                        return Math.min(Math.max(parseInt(px, 10), 0), maxPx);        
                };                 
                
                function locate(){
                        var curleft = 0,
                            curtop  = 0,
                            obj     = outerWrapper;
                            
                        // Try catch for IE's benefit
                        try {
                                while (obj.offsetParent) {
                                        curleft += obj.offsetLeft;
                                        curtop  += obj.offsetTop;
                                        obj      = obj.offsetParent;
                                };
                        } catch(err) {};
                        x = curleft;
                        y = curtop;
                };
                
                function onTimer() {
                        var xtmp = vertical ? handle.offsetTop : handle.offsetLeft;
                        xtmp = Math.round((destPos < xtmp) ? Math.max(destPos, Math.floor(xtmp - deltaPx)) : Math.min(destPos, Math.ceil(xtmp + deltaPx)));                  
                        pixelsToValue(xtmp);
                        if(xtmp != destPos) timer = setTimeout(onTimer, steps > 20 ? 50 : 100);
                        else kbEnabled = true;
                };

                var tween = function(){
                        frame++;
                        var c = tweenC,
                            d = 20,
                            t = frame,
                            b = tweenB,
                            x = Math.ceil((t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b);

                        pixelsToValue(t == d ? tweenX : x);
                        callback("move");
                        if(t!=d) timer = setTimeout(tween, 20);
                        else {
                                clearTimeout(timer);
                                timer     = null;
                                kbEnabled = true;
                        };
                };

                function tweenTo(tx){
                        kbEnabled = false;
                        tweenX = parseInt(tx, 10);
                        tweenB = parseInt(vertical ? handle.style.top : handle.style.left, 10);
                        tweenC = tweenX - tweenB;
                        tweenD = 20;
                        frame  = 0;
                        if(!timer) timer = setTimeout(tween, 20);
                };
                
                function pixelsToValue(px) {                       
                        handle.style[vertical ? "top" : "left"] = px + "px";                                                                                                                              
                        var val = min + (Math.round(px / stepPx) * inc);                                                                                                                                                      
                        setInputValue((tagName == "select" || inc == 1) ? Math.round(val) : val);                         
                };
                
                function valueToPixels(val) {
                        var value = isNaN(val) ? tagName == "input" ? parseFloat(inp.value) : inp.selectedIndex : val;
                        if(isNaN(value) || value < Math.min(min,max)) value = Math.min(min,max);
                        else if(value > Math.max(min,max)) value = Math.max(min,max);                         
                        setInputValue(value);                                                                    
                        handle.style[vertical ? "top" : "left"] = Math.round(((value - min) / inc) * stepPx) + "px";                                                                                                                                 
                };

                function setInputValue(val) {                                             
                        val = isNaN(val) ? min : val; 
                        if(tagName == "select") {
                                try {                                               
                                        val = parseInt(val, 10);
                                        if(inp.selectedIndex == val) return;
                                        inp.options[val].selected = true;                                                                             
                                } catch (err) {};
                        } else {                                                                                                                                                                                                                                                                               
                                val = (min + (Math.round((val - min) / inc) * inc)).toFixed(precision);    
                                if(inp.value == val) return;
                                inp.value = val;                                 
                        };
                        updateAriaValues();                        
                        callback("update");
                };
                
                function findLabel() {
                        var label;
                        if(inp.parentNode && inp.parentNode.tagName.toLowerCase() == "label") label = inp.parentNode;
                        else {
                                var labelList = document.getElementsByTagName('label');
                                // loop through label array attempting to match each 'for' attribute to the id of the current element
                                for(var i = 0, lbl; lbl = labelList[i]; i++) {
                                        // Internet Explorer requires the htmlFor test
                                        if((lbl['htmlFor'] && lbl['htmlFor'] == inp.id) || (lbl.getAttribute('for') == inp.id)) {
                                                label = lbl;
                                                break;
                                        };
                                };
                        };
                        if(label && !label.id) { label.id = inp.id + "_label"; };
                        return label;
                };
                
                function updateAriaValues() {
                        handle.setAttribute("aria-valuenow",  tagName == "select" ? inp.options[inp.selectedIndex].value : inp.value);
                        handle.setAttribute("aria-valuetext", tagName == "select" ? inp.options[inp.selectedIndex].text  : inp.value);
                };
                
                function onChange( e ) {
                        valueToPixels();
                        callback("update"); 
                        return true;
                };                  
                
                (function() { 
                        if(hideInput) { inp.className += " fd_hide_slider_input"; }
                        else { addEvent(inp, 'change', onChange); };
                        
                        outerWrapper              = document.createElement('div');
                        outerWrapper.className    = "fd-slider" + (vertical ? "-vertical " : " ") + classNames;
                        outerWrapper.id           = "fd-slider-" + inp.id;

                        wrapper                   = document.createElement('span');
                        wrapper.className         = "fd-slider-inner";

                        bar                       = document.createElement('span');
                        bar.className             = "fd-slider-bar";

                        if(fullARIA) {
                                handle            = document.createElement('span');
                                handle.setAttribute(!/*@cc_on!@*/false ? "tabIndex" : "tabindex", "0");
                        } else {
                                handle            = document.createElement('button');                                 
                                handle.setAttribute("type", "button");
                        };
                        
                        handle.className          = "fd-slider-handle";                        
                        handle.appendChild(document.createTextNode(String.fromCharCode(160)));                         
                        
                        outerWrapper.appendChild(wrapper);
                        outerWrapper.appendChild(bar);
                        outerWrapper.appendChild(handle);
                        
                        inp.parentNode.insertBefore(outerWrapper, inp);

                        /*@cc_on@*/
                        /*@if(@_win32)
                        handle.unselectable       = "on";
                        bar.unselectable          = "on";
                        wrapper.unselectable      = "on";
                        outerWrapper.unselectable = "on";
                        /*@end@*/

                        addEvent(outerWrapper, "mouseover", onMouseOver);
                        addEvent(outerWrapper, "mouseout",  onMouseOut);
                        addEvent(outerWrapper, "mousedown", onMouseDown);                        
                        if(!window.opera) {
                                addEvent(handle, "keydown",   onKeyDown);  
                                addEvent(handle, "keypress",  onKeyPress); 
                        } else {
                                addEvent(handle, "keypress",  onKeyDown);
                        };
                        addEvent(handle, "focus",     onFocus);
                        addEvent(handle, "blur",      onBlur);                       
                        addEvent(handle, "mousedown", onHandleMouseDown);
                        addEvent(handle, "mouseup",   onHandleMouseUp); 
                        
                        // Add ARIA accessibility info programmatically                         
                        handle.setAttribute("role",           "slider");
                        handle.setAttribute("aria-valuemin",  min);
                        handle.setAttribute("aria-valuemax",  max);                     
                        
                        var lbl = findLabel();
                        if(lbl) {                                 
                                handle.setAttribute("aria-labelledby", lbl.id);
                                handle.id = "fd-slider-handle-" + inp.id;
                                /*@cc_on
                                /*@if(@_win32)
                                lbl.setAttribute("htmlFor", handle.id);
                                @else @*/
                                lbl.setAttribute("for", handle.id);
                                /*@end
                                @*/
                        };
                        
                        // Are there page instructions - the creation of the instructions has been left up to you fine reader...
                        if(document.getElementById("fd_slider_describedby")) {                                  
                                handle.setAttribute("aria-describedby", "fd_slider_describedby");  // aaa:describedby
                        };
                                                       
                        updateAriaValues();                        
                        callback("create");                            
                        redraw();                                                                                  
                })();
               
                return {
                        onResize:       function(e) { if(outerWrapper.offsetHeight != sliderH || outerWrapper.offsetWidth != sliderW) { redraw(); }; },
                        destroy:        function()  { destroySlider(); },
                        reset:          function()  { valueToPixels(); },
                        increment:      function(n) { incrementHandle(n); }
                };
        }; 
           
        addEvent(window, "load",   init);
        addEvent(window, "unload", unload);
        addEvent(window, "resize", resize);
        /*@cc_on@*/
        /*@if(@_win32)
        var onload = function(e) {
                for(slider in sliders) { sliders[slider].reset(); }
        };                   
        addEvent(window, "load", function() { setTimeout(onload, 200) });
        /*@end@*/
                
        return {                          
                        create:                 function(elem) { init(elem) },                        
                        destroyAll:             function() { destroyAllsliders(); },
                        destroySlider:          function(id) { return destroySingleSlider(id); },
                        redrawAll:              function() { resize(); },
                        increment:              function(id, numSteps) { if(!(id in sliders)) { return false; }; sliders[id].increment(numSteps); },
                        addEvent:               addEvent,
                        removeEvent:            removeEvent,
                        stopEvent:              stopEvent,
                        disableMouseWheel:      function() { removeMouseWheelSupport(); },
                        removeOnLoadEvent:      function() { removeOnloadEvent(); }                      
        }
})();